﻿using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace TimeSolve
{
    /// <summary>
    /// ChartControl.xaml 的交互逻辑
    /// </summary>
    public partial class MonitorControl : UserControl, INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        public void RaisePropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        public MonitorControl()
        {
            InitializeComponent();
            this.DataContext = this;
            xlabels = new List<TextBlock>();
            ylabels = new List<TextBlock>();
            xlines = new List<Line>();
            ylines = new List<Line>();
            for (int i = 0; i < 20; i++)
            {
                TextBlock t = new TextBlock() { };
                vChartData.Children.Add(t);
                xlabels.Add(t);
                Canvas.SetBottom(t, -20);
                TextBlock t2 = new TextBlock() { };
                vChartData.Children.Add(t2);
                ylabels.Add(t2);
                Line l = new Line() { Stroke = Brushes.Gray, StrokeThickness = 1 };
                vChartData.Children.Add(l);
                xlines.Add(l);
                Line l2 = new Line() { Stroke = Brushes.Gray, StrokeThickness = 1 };
                vChartData.Children.Add(l2);
                ylines.Add(l2);
            }
            polylines = new List<Polyline>();
            for (int i = 0; i < 10; i++)
            {
                Polyline pl = new Polyline();
                pl.StrokeThickness = 1;
                vChartData.Children.Add(pl);
                polylines.Add(pl);
            }
        }
        public MonitorItem monitorItem { get => _monitorItem; set { _monitorItem = value; RaisePropertyChanged("monitorItem"); } }
        private MonitorItem _monitorItem;
        public List<TextBlock> xlabels { get; set; }
        public List<TextBlock> ylabels { get; set; }
        public List<Line> xlines { get; set; }
        public List<Line> ylines { get; set; }
        public List<Polyline> polylines { get; set; }
 
        private axisData xAxisData = new axisData();
        private axisData yAxisData = new axisData();
        private void xAxisDataChanged()
        {
            for (int i = 0; i < xlabels.Count; i++)
            {
                double v = xAxisData.min + i * xAxisData.space;
                if (v <= xAxisData.max)
                {
                    double vToScreen = xAxisData.xToScreen(v);
                    xlabels[i].Text = v.ToString("g3");
                    Canvas.SetLeft(xlabels[i], vToScreen - 0.5 * xlabels[i].ActualWidth);
                    xlines[i].X1 = vToScreen;
                    xlines[i].X2 = vToScreen;
                    xlines[i].Y2 = yAxisData.visualLength;
                }
                else
                {
                    if (xlabels[i].Text == "") break;
                    xlabels[i].Text = "";
                    xlines[i].Y2 = 0;
                }
            }
        }
        private void yAxisDataChanged()
        {
            for (int i = 0; i < ylabels.Count; i++)
            {
                double v = yAxisData.min + i * yAxisData.space;
                if (v <= yAxisData.max)
                {
                    double vToScreen = yAxisData.yToScreen(v);
                    ylabels[i].Text = v.ToString("g3");
                    Canvas.SetTop(ylabels[i], vToScreen - 0.5 * ylabels[i].ActualHeight);
                    Canvas.SetLeft(ylabels[i], -ylabels[i].ActualWidth - 5);
                    ylines[i].X2 = xAxisData.visualLength;
                    ylines[i].Y1 = ylines[i].Y2 = vToScreen;
                }
                else
                {
                    if (ylabels[i].Text == "") break;
                    ylabels[i].Text = "";
                    ylines[i].X2 = 0;
                }
            }
        }
        public void loadMonitor(MonitorItem monitorItem)
        {            
            this.monitorItem = monitorItem; 
            update();
        }
        public void update()
        {
            if (monitorItem == null) return;
            updateLines();
        }

        public void updateLines()
        {
            bool xc = xAxisData.checkChangeMinMax(monitorItem.minX, monitorItem.maxX);
            bool yc = yAxisData.checkChangeMinMax(monitorItem.minY, monitorItem.maxY);
            if (xc)
            {
                xAxisDataChanged();
            }
            if (yc)
            {
                yAxisDataChanged();
            }
            PointCollection[] plist = new PointCollection[monitorItem.datas.Count];
            for (int i1=0;i1<plist.Length;i1++)
            {
                plist[i1] = new PointCollection();
                for (int i2 = 0; i2 < monitorItem.xValues.Count; i2++)
                {
                    plist[i1].Add(new Point(
                        (monitorItem.xValues[i2] - xAxisData.min) * xAxisData.visualRate,
                        (yAxisData.max - monitorItem.datas[i1].yValues[i2]) * yAxisData.visualRate));
                }
            }

            for(int i1 = 0; i1 < polylines.Count; i1++)
            {
                if (i1 < plist.Length)
                {
                    polylines[i1].Points = plist[i1];
                    polylines[i1].Stroke = monitorItem.datas[i1].dataBrush;
                }
                else
                {
                    if(polylines[i1].Points != null)
                    {
                        polylines[i1].Points = null;
                    }else
                    {
                        break;
                    }
                }
            }

        }

        private void vChart_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            bool xc = xAxisData.checkChangeVisualLength(vChart.ActualWidth);
            bool yc = yAxisData.checkChangeVisualLength(vChart.ActualHeight);
            if (xc)
            {
                xAxisDataChanged();
            }
            if (yc)
            {
                yAxisDataChanged();
            }
        }


        public struct axisData
        {
            public bool isLog;
            public double min;
            public double max;
            public double space;
            public double visualLength;
            public double visualRate;
            public bool checkChangeVisualLength(double length)
            {
                if (this.visualLength == length)
                {
                    return false;
                }else
                {
                    this.visualLength = length;
                    visualRate = (max - min) > 0 ? visualLength / (max - min) : 1;
                    return true;
                }
            }
            public bool checkChangeMinMax(double dataMin, double dataMax)
            {
                double newspace = calSpace(dataMin, dataMax);
                double newmin = ((int)(dataMin / newspace)) * newspace;
                double newmax = ((int)(dataMax / newspace) + 1) * newspace;
                if (newmin == min && newmax == max )
                {
                    return false;
                }else
                {
                    min = newmin;
                    max = newmax;
                    space = newspace;
                    visualRate = visualLength / (max - min);
                    return true;
                }
            }
            public double xToScreen(double x)
            {
                return (x - min) * visualRate;
            }
            public double yToScreen(double y)
            {
                return (max - y) * visualRate;
            }
            private double calSpace(double min, double max)
            {
                double deltaX = max - min;
                if (deltaX <= 0) { deltaX = 1; }
                string[] ss = (deltaX / 5).ToString("E").Split('E');//数字是最少的间隔数量
                double a = double.Parse(ss[0]);
                if (a >= 5)
                {
                    a = 5;
                }
                else if (a >= 2)
                {
                    a = 2;
                }
                else
                {
                    a = 1;
                }
                a *= Math.Pow(10, int.Parse(ss[1]));
                return a;
            }
        }

    }

}


//public double upL { get; set; }
//public double downL { get; set; }
//public double leftL { get; set; }
//public double rightL { get; set; }

//public void update()
//{
//    if (monitorItem == null) return;
//    if (xAxisData.isAxisNeedToChange(monitorItem.minX, monitorItem.maxX))
//    {
//        for (int i = 0; i < xlabels.Count; i++)
//        {
//            double v = xAxisData.min + i * xAxisData.space;
//            if (v <= xAxisData.max)
//            {
//                double vToScreen = xAxisData.xToScreen(v);
//                xlabels[i].Text = v.ToString("g3");
//                Canvas.SetLeft(xlabels[i], vToScreen - 0.5 * xlabels[i].ActualWidth);
//                xlines[i].X1 = vToScreen;
//                xlines[i].X2 = vToScreen;
//                xlines[i].Y2 = yAxisData.visualLength;
//            }
//            else
//            {
//                if (xlabels[i].Text == "") break;
//                xlabels[i].Text = "";
//                xlines[i].Y2 = 0;
//            }
//        }
//    }
//    if (yAxisData.isAxisNeedToChange(monitorItem.minY, monitorItem.maxY))
//    {
//        for (int i = 0; i < ylabels.Count; i++)
//        {
//            double v = yAxisData.min + i * yAxisData.space;
//            if (v <= yAxisData.max)
//            {
//                double vToScreen = yAxisData.yToScreen(v);
//                ylabels[i].Text = v.ToString("g3");
//                Canvas.SetTop(ylabels[i], vToScreen - 0.5 * ylabels[i].ActualHeight);
//                Canvas.SetLeft(ylabels[i], -ylabels[i].ActualWidth - 5);
//                ylines[i].X2 = xAxisData.visualLength;
//                ylines[i].Y1 = ylines[i].Y2 = vToScreen;
//            }
//            else
//            {
//                if (ylabels[i].Text == "") break;
//                ylabels[i].Text = "";
//                ylines[i].X2 = 0;
//            }
//        }
//    }            

//}

//public bool isAxisNeedToChange(double dataMin, double dataMax)
//{
//    double newspace = calSpace(dataMin, dataMax);
//    double newmin = ((int)(dataMin / newspace)) * newspace;
//    double newmax = ((int)(dataMax / newspace) + 1) * newspace;
//    double newvisualRate = visualLength / (newmax - newmin);
//    if (newmin == min && newmax == max && newvisualRate == visualRate)
//    {
//        return false;
//    }
//    else
//    {
//        min = newmin;
//        max = newmax;
//        space = newspace;
//        visualRate = newvisualRate;
//        return true;
//    }
//}